#region Imported Namespaces
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Text.RegularExpressions;

using BO = PHSRAG.Insight21.BusinessObjects;
using DataAccess = PHSRAG.Utility.DataAccess;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using SearchCriteria = PHSRAG.Insight21.SearchContext.SearchCriteria;
using PHSRAG.Insight21.InsightUtilities;
#endregion

namespace PHSRAG.Insight21.Humans
{
	/// <summary>
	/// The WorkInProgressProtocolProcess object will be used to list all the protocolprocess available for the logged in user. 
	/// Also supports the user to filter and sort based on the searchCriteria.
	/// </summary>
	public class WorkInProgressProtocolProcesses : BO.BusinessObject
	{
		#region Constants
		private const string	WorkInProgressProtocolProcessesKey = "WorkInProgressProtocolProcesses_8B49C6CC-26B7-4957-86F2-4C62D6CA5FCF";
		private const bool		AscendingSortSequence = true;
		private const string	FilteredDataTableName = "filtered";
		private const string	OriginalDataTableName = "original";
		#endregion

		#region Instance Variables
		private Hashtable		WorkInProgressProtocolProcessesMap = new Hashtable();
		private string			currentDataTableName = OriginalDataTableName;
		private bool			sortAscending = AscendingSortSequence;
		private string			sortColumn = "ProtocolNumber";	// Keep this in sync with what the stored proc order by
		#endregion

		#region Constructor
		/// <summary>
		/// Constructs a new WorkInProgressProtocolProcess object based on the Cache Policy passed in as a parameter. 
		/// All the instance variables will be set to default values of their associated types.
		/// </summary>
		/// <param name="cachePolicy">available cachepolicy</param>
		public WorkInProgressProtocolProcesses(ICachePolicy cachePolicy) : base(cachePolicy)
		{
		}
		#endregion

		#region Public Properties
		/// <summary>
		/// Get the key to be used in all caching operations for this instance of the object.
		/// </summary>
		public static string CacheKey	{ get { return WorkInProgressProtocolProcessesKey; } }

		/// <summary>
		/// Get the total number of Protocol Processes.
		/// </summary>
		public int Count
		{
			get
			{
				return ( null == DataContainer )? 0 :DataContainer.Tables[0].Rows.Count;
			}
		}
		
		/// <summary>
		/// Get the sort order.
		/// </summary>
		public bool SortAscending
		{
			get { return sortAscending; }
		}

		/// <summary>
		/// Get the name of the sort column.
		/// </summary>
		public string SortColumn
		{
			get { return sortColumn; }
		}
		#endregion

		#region caching
		/// <summary>
		/// Cache the current instance using the prevalent cache policy.
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache(CacheKey, this);
		}

		/// <summary>
		/// Remove the current instance from the cache using the prevalent cache policy.
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(CacheKey);
		}
		#endregion

		#region Public Load Methods

		/// <summary>
		/// Load the current instance with protocol processes for the current user.
		/// </summary>
		/// <param name="connectionString">Database connection string</param>
		/// <param name="args">Is expected to contain a single argument - the domain user ID</param>
		public override void Load(string connectionString, params object[] args)
		{
			Load( connectionString, null, args );
		}

		/// <summary>
		/// When the page is initially loaded,a WorkInProgressProtocolProcesses object will be created,loaded,and stored in the cache.
		/// When the WorkInProgressProtocolProcesses finds a search criteria,the load method will be called passing the cached Search conetxt and the userContext via the Params Object[] parameter.
		/// else the load method is called via the user context via the params[] object.
		/// </summary>
		/// <param name="connectionString"></param>
		/// <param name="args"></param>
		/// <param name="searchCriteria"></param>
		public void Load(string connectionString, SearchCriteria searchCriteria, params object[] args)
		{
			try
			{
				if (args.Length != 1)
				{
					throw new Exception("WorkInProgressProtocolProcesses load requires a domain user ID");
				}
				else if(searchCriteria != null) 
				{
					WorkInProgressProtocolProcessesMap.Clear();
							
					DataContainer = DataAccess.GetDataSet(connectionString, "GetWipProtocolProcesses",
						DataAccess.BuildSqlParameterArray("@domainUserId", SqlDbType.Int, (int)args[0]
						,"@protocolNumber",SqlDbType.VarChar,(null==searchCriteria["protocolNumber"]) ? (object)DBNull.Value : searchCriteria["protocolNumber"].TrimEnd('*')
						,"@protocolTitle",SqlDbType.VarChar,(null==searchCriteria["protocolTitle"]) ? (object)DBNull.Value : searchCriteria["protocolTitle"].TrimEnd('*')
						,"@pIID",SqlDbType.Int,(null==searchCriteria["PI"]) ? (object)DBNull.Value : searchCriteria["PI"]
						,"@organizationIds",SqlDbType.VarChar,(null==searchCriteria["organizationId"]) ? (object)DBNull.Value : searchCriteria["organizationId"]
						));
				}
				else
				{
					DataContainer = DataAccess.GetDataSet(connectionString, "GetWipProtocolProcesses",
						DataAccess.BuildSqlParameterArray("@domainUserId", SqlDbType.Int, (int)args[0]));
				}
			
				if ( DataContainer.Tables.Count == 1 )
					DataContainer.Tables[0].TableName = OriginalDataTableName;
			}
			catch(Exception ex)
			{
				Utility.ExceptionReport.WriteToEventLog ("Failed to load the WorkInProgress,Error occurred while executing the Load()", ex, true, Utility.ExceptionReport.ReportType.Error);
				throw;
			}
		}

		#endregion

		#region Public Methods

		/// <summary>
		/// Get the list of protocolProcess objects bound by a start and end index. These indeces are in the list
		/// loaded during the Load() method into the data container. Typically, the start index
		/// is on a "page" boundary, where the "page" referes to a datagrid page.
		/// Note that the total number of objects returned may be less than the requested count.
		/// We maintain a Hashtable of ArrayList objects using the start index as the key. This allows us to retrieve the
		/// the objects associated with the index, thereby directly supporting random access based the
		/// page index.
		/// </summary>
		/// <param name="startIndex">Index within the list to begin</param>
		/// <param name="count">Total number of objects to load</param>
		/// <returns>The list of WorkInProgressProtocolProcesses objects</returns>

		public DataTable GetWIPList(int startIndex, int count)
		{
			DataTable workInProgressList;
			try
			{
				workInProgressList = WorkInProgressProtocolProcessesMap[startIndex] as DataTable;
				if (workInProgressList == null)
				{
					workInProgressList=new DataTable();
					
					DataTable dataTable=DataContainer.Tables[currentDataTableName]; 
					workInProgressList=dataTable.Clone();
					int rowCount=dataTable.Rows.Count;
					for (int i = startIndex, end = Math.Min(i + count,rowCount); i < end; ++i)
					{
						workInProgressList.LoadDataRow(dataTable.Rows[i].ItemArray,true);
						WorkInProgressProtocolProcessesMap[startIndex] = workInProgressList;
					}
				
				}
			}
			catch(Exception ex)
			{
				Utility.ExceptionReport.WriteToEventLog ("Failed to get the WorkInProgressList,Error occurred while executing the GetList()", ex, true, Utility.ExceptionReport.ReportType.Error);
				throw;
			}
			return workInProgressList;
		}

		/// <summary>
		/// Sort the list by the specified column.
		/// If the column to be sorted is the same as what was last sorted on, the sort sequence is toggled. 
		/// Else, the sort sequence is set to ascending.
		/// </summary>
		/// <param name="columnName">Column to sort by</param>
		public void Sort(string columnName)
		{
			WorkInProgressProtocolProcessesMap.Clear();
			sortAscending = (sortColumn == columnName) ? !sortAscending : AscendingSortSequence;
			sortColumn = columnName;

			DataTable dataTable = DataContainer.Tables[currentDataTableName];
			DataView dataView = dataTable.DefaultView;
			dataView.Sort = string.Format("{0} {1}", columnName, sortAscending ? SortSequenceAscending : SortSequenceDescending);

			DataTable sortedDataTable = dataTable.Clone();
			foreach (DataRowView rowView in dataView)
			{
				sortedDataTable.ImportRow(rowView.Row);
			}
			DataContainer.Tables.Remove(currentDataTableName);
			DataContainer.Tables.Add(sortedDataTable);
		}

		/// <summary>
		/// Returns a dataTable of applications for use when downloading to an application
		/// such as excel or pdf
		/// </summary>
		/// <returns></returns>
		public DataTable GetApplicationsForDownload()
		{
			if ( null == DataContainer  ||  DataContainer.Tables.Count < 1 )
			{
			throw new Exception("Failed to get the WorkInProgressList for download,Error occurred while executing the GetApplicationsForDownload()");
			}
			return DataContainer.Tables[currentDataTableName];
		}
		#endregion

		#region constants
		private const string SortSequenceAscending="ASC";
		private const string SortSequenceDescending="DESC";
		#endregion
	}
}

